package org.huiway.huipicturebackend.controller;

import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.huiway.huipicturebackend.annotation.AuthCheck;
import org.huiway.huipicturebackend.common.BaseResponse;
import org.huiway.huipicturebackend.common.DeleteRequest;
import org.huiway.huipicturebackend.common.ResultUtils;
import org.huiway.huipicturebackend.constant.UserConstant;
import org.huiway.huipicturebackend.exception.BusinessException;
import org.huiway.huipicturebackend.exception.ErrorCode;
import org.huiway.huipicturebackend.exception.ThrowUtils;
import org.huiway.huipicturebackend.mapper.PictureMapper;
import org.huiway.huipicturebackend.mapper.SpaceMapper;
import org.huiway.huipicturebackend.model.dto.picture.PictureUploadRequest;
import org.huiway.huipicturebackend.model.dto.user.*;
import org.huiway.huipicturebackend.model.entity.Picture;
import org.huiway.huipicturebackend.model.entity.User;
import org.huiway.huipicturebackend.model.vo.user.LoginUserVO;
import org.huiway.huipicturebackend.model.vo.user.UserSelfVO;
import org.huiway.huipicturebackend.model.vo.user.UserVO;
import org.huiway.huipicturebackend.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

import static org.huiway.huipicturebackend.constant.UserConstant.DEFAULT_AVATAR;

/**
 *
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;
    @Resource
    private PictureMapper pictureMapper;
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private SpaceMapper spaceMapper;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 用户注册
     *
     * @param userRegisterRequestStr
     * @param pictureUploadRequestStr
     * @param multipartFile
     * @return
     */
    @PostMapping(value = "/register", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public BaseResponse<Long> userRegister(
            @RequestPart(value = "userRegisterRequest") String userRegisterRequestStr,
            @RequestPart(value = "pictureUploadRequest", required = false) String pictureUploadRequestStr,
            @RequestPart(value = "file", required = false) MultipartFile multipartFile
    ) {
        try {
            //反序列化 JSON 字符串成对象
            UserRegisterRequest userRegisterRequest = objectMapper.readValue(userRegisterRequestStr, UserRegisterRequest.class);
            PictureUploadRequest pictureUploadRequest = StringUtils.hasText(pictureUploadRequestStr)
                    ? objectMapper.readValue(pictureUploadRequestStr, PictureUploadRequest.class)
                    : new PictureUploadRequest();
            //头像存储特殊处理，给初始头像一个专门的存储空间
            pictureUploadRequest.setSpaceId(11L);
            //验证邮箱验证码
            String code = userRegisterRequest.getCode();
            log.info("邮箱验证码 :{}", code);
            String email = userRegisterRequest.getEmail();
            log.info("邮箱 :{}", email);
            String s = redisTemplate.opsForValue().get(email);
            log.info("从redis中获取code->{}", s);
            if (ObjUtil.equal(code, s)) {
                log.info("验证码正确{}", code);
                //业务处理
                long result = userService.userRegister(userRegisterRequest, multipartFile, pictureUploadRequest);
                return ResultUtils.success(result);
            } else {
                log.info("验证码错误{}", s);
                return (BaseResponse<Long>) ResultUtils.error(ErrorCode.PARAMS_ERROR, "验证码错误");
            }
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数解析失败: " + e.getMessage());
        }

    }


    /**
     * 用户登录
     *
     * @param userLoginRequest
     * @param request
     * @return
     */
    @PostMapping("/login")
    public BaseResponse<LoginUserVO> userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(userLoginRequest == null, ErrorCode.PARAMS_ERROR);
        // 2.检查验证码是否正确
        String redisCodeValue = redisTemplate.opsForValue().get(userLoginRequest.getCodeKey());
        if(!StringUtils.hasLength(redisCodeValue) ||
                !redisCodeValue.equals(userLoginRequest.getCheckCode())) {
            // 验证码不正确
            BaseResponse<?> error = ResultUtils.error(ErrorCode.PARAMS_ERROR, "验证码错误");
            return (BaseResponse<LoginUserVO>)error;
        }
        String userAccount = userLoginRequest.getUserAccount();
        String email = userLoginRequest.getEmail();
        String userPassword = userLoginRequest.getUserPassword();
        LoginUserVO loginUserVO = userService.userLogin(userAccount, email, userPassword, request);
        return ResultUtils.success(loginUserVO);
    }

    /**
     * 获取当前登录用户（脱敏）
     *
     * @param request
     * @return
     */
    @GetMapping("/get/login")
    public BaseResponse<LoginUserVO> getLoginUser(HttpServletRequest request) {
        User user = userService.getLoginUser(request);
        return ResultUtils.success(userService.getLoginUserVO(user));
    }

    /**
     * 本人修改用户信息
     *
     * @param userSelfVOStr
     * @param pictureUploadRequestStr
     * @param multipartFile
     * @param request
     * @return
     */
    @PostMapping(value = "/update/self", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public BaseResponse<Boolean> updateUserSelf(
            @RequestPart(value = "userSelfVO") String userSelfVOStr,
            @RequestPart(value = "pictureUploadRequest", required = false) String pictureUploadRequestStr,
            @RequestPart(value = "file", required = false) MultipartFile multipartFile,
            HttpServletRequest request
    ) {
        try {
            // 反序列化 JSON 字符串成对象
            UserSelfVO userSelfVO = objectMapper.readValue(userSelfVOStr, UserSelfVO.class);
            PictureUploadRequest pictureUploadRequest = StringUtils.hasText(pictureUploadRequestStr)
                    ? objectMapper.readValue(pictureUploadRequestStr, PictureUploadRequest.class)
                    : new PictureUploadRequest();
            //验证邮箱验证码
            String code ;
            String email ;

            code = userSelfVO.getCode();
            log.info("邮箱验证码 :{}", code);
            email = userSelfVO.getEmail();
            log.info("邮箱 :{}", email);

            User loginUser = userService.getLoginUser(request);
            // 业务处理
            userSelfVO.setId(loginUser.getId());
            if (loginUser.getUserAvatar() != null && !loginUser.getUserAvatar().equals(DEFAULT_AVATAR)) {
                QueryWrapper<Picture> queryWrapperPicture = new QueryWrapper<>();
                queryWrapperPicture.eq("url", loginUser.getUserAvatar());
                Picture picture = pictureMapper.selectOne(queryWrapperPicture);
                pictureUploadRequest.setId(picture.getId());
            }
            //头像存储特殊处理，给头像一个专门的存储空间。
            pictureUploadRequest.setSpaceId(11L);

            //如果要修改邮箱
            if (email != null && code != null) {
                //验证码验证
                String s = redisTemplate.opsForValue().get(email);
                log.info("从redis中获取code->{}", s);
                if (ObjUtil.equal(code, s)) {
                    log.info("验证码正确{}", code);
                    boolean success = userService.updateUserSelf(userSelfVO, pictureUploadRequest, multipartFile, loginUser);
                    return ResultUtils.success(success);
                } else {
                    log.info("验证码错误{}", s);
                    return (BaseResponse<Boolean>) ResultUtils.error(ErrorCode.PARAMS_ERROR, "验证码错误");
                }
            }
            boolean success = userService.updateUserSelf(userSelfVO, pictureUploadRequest, multipartFile, loginUser);
            return ResultUtils.success(success);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数解析失败: " + e.getMessage());
        }
    }

    /**
     * 重置密码
     *
     * @param resetPasswordRequest
     * @param request
     * @return
     */
    @PostMapping("/reset/password")
    public BaseResponse<Boolean> resetPassword(@RequestBody ResetPasswordRequest resetPasswordRequest, HttpServletRequest request) {
        ThrowUtils.throwIf(resetPasswordRequest == null, ErrorCode.PARAMS_ERROR);
        User loginUser = userService.getLoginUser(request);
        //验证邮箱验证码
        String email = resetPasswordRequest.getEmail();
        log.info("邮箱 :{}", email);
        String code = resetPasswordRequest.getCode();
        log.info("邮箱验证码 :{}", code);
        //验证码验证
        String s = redisTemplate.opsForValue().get(email);
        log.info("从redis中获取code->{}", s);
        if (ObjUtil.equal(code, s)) {
            log.info("验证码正确{}", code);
            if (resetPasswordRequest.getUserPassword() == null || resetPasswordRequest.getCheckPassword() == null) {
                return (BaseResponse<Boolean>) ResultUtils.error(ErrorCode.PARAMS_ERROR, "密码不能为空");
            }
            boolean result = userService.resetPassword(resetPasswordRequest, loginUser);
            return ResultUtils.success(result);
        } else {
            log.info("验证码错误{}", s);
            return (BaseResponse<Boolean>) ResultUtils.error(ErrorCode.PARAMS_ERROR, "验证码错误");
        }

    }

    /**
     * 用户退出登录
     *
     * @param request
     * @return
     */
    @PostMapping("/logout")
    public BaseResponse<Boolean> userLogout(HttpServletRequest request) {
        ThrowUtils.throwIf(request == null, ErrorCode.PARAMS_ERROR);
        boolean result = userService.userLogout(request);
        return ResultUtils.success(result);
    }

    /**
     * 创建用户
     *
     * @param userAddRequest
     * @return
     */
    @PostMapping("/add")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Long> addUser(@RequestBody UserAddRequest userAddRequest) {
        ThrowUtils.throwIf(userAddRequest == null, ErrorCode.PARAMS_ERROR);
        User user = new User();
        BeanUtils.copyProperties(userAddRequest, user);
        // 默认密码 12345678
        final String DEFAULT_PASSWORD = "12345678";
        String encryptPassword = userService.getEncryptPassword(DEFAULT_PASSWORD);
        user.setUserPassword(encryptPassword);
        boolean result = userService.save(user);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(user.getId());
    }

    /**
     * 根据 id 获取用户（仅管理员）
     *
     * @param id
     * @return
     */
    @GetMapping("/get")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<User> getUserById(long id) {
        ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR);
        User user = userService.getById(id);
        ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR);
        return ResultUtils.success(user);
    }

    /**
     * 根据 id 获取包装类
     *
     * @param id
     * @return
     */
    @GetMapping("/get/vo")
    public BaseResponse<UserVO> getUserVOById(long id) {
        BaseResponse<User> response = getUserById(id);
        User user = response.getData();
        return ResultUtils.success(userService.getUserVO(user));
    }

    /**
     * 删除用户
     *
     * @param deleteRequest
     * @return
     */
    @PostMapping("/delete")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> deleteUser(@RequestBody DeleteRequest deleteRequest) {
        if (deleteRequest == null || deleteRequest.getId() <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        boolean b = userService.removeById(deleteRequest.getId());
        return ResultUtils.success(b);
    }

    /**
     * 更新用户
     *
     * @param userUpdateRequest
     * @return
     */
    @PostMapping("/update")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> updateUser(@RequestBody UserUpdateRequest userUpdateRequest) {
        ThrowUtils.throwIf(userUpdateRequest == null || userUpdateRequest.getId() <= 0, ErrorCode.PARAMS_ERROR);
        User user = new User();
        BeanUtils.copyProperties(userUpdateRequest, user);
        boolean result = userService.updateById(user);
        ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
        return ResultUtils.success(true);
    }

    /**
     * 分页获取用户封装列表（仅管理员）
     *
     * @param userQueryRequest 查询请求参数
     */
    @PostMapping("/list/page/vo")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<UserVO>> listUserVOByPage(@RequestBody UserQueryRequest userQueryRequest) {
        ThrowUtils.throwIf(userQueryRequest == null, ErrorCode.PARAMS_ERROR);
        long current = userQueryRequest.getCurrent();
        long pageSize = userQueryRequest.getPageSize();
        Page<User> userPage = userService.page(new Page<>(current, pageSize),
                userService.getQueryWrapper(userQueryRequest));
        Page<UserVO> userVOPage = new Page<>(current, pageSize, userPage.getTotal());
        List<UserVO> userVOList = userService.getUserVOList(userPage.getRecords());
        userVOPage.setRecords(userVOList);
        return ResultUtils.success(userVOPage);
    }

}

